#define START_LEVEL 0
#define MOVE_UP 1
#define MOVE_RIGHT 2
#define MOVE_DOWN 3
#define MOVE_LEFT 4
#define EAT_FOOD 5
#define COLLIDE_WALL 6
#define COLLIDE_BODY 7
#define RUNNING 8
#define FINISH_LEVEL 9

#define NONE 0
#define WALL 1
#define FOOD 2
#define BODY 3
#define HEAD 4

#define LEVEL_MAX 5
#define UNIT_WIDTH 10

static int _snake_max_length;
static int _snake_length;
static int _snake_state;
static int[][] _snake = null; //_snake = int[max_length][2]
static int _level;
static int _table_width;
static int _table_height;
static int[][] _table;
static Image imgGameplayBG = null;
static int _snake_direction = MOVE_UP;
static int _snake_speed = 400;
static long _startTime;
static int _food_x;
static int _food_y;

static String strLevel;

static void InitTable()
{
	_table = new int[_table_width][_table_height];
	for(int i=0; i<_table_height; i++)
	{
		_table[0][i] = WALL;
		_table[_table_width - 1][i] = WALL;
	}
	for(int i=0; i<_table_width; i++)
	{
		_table[i][0] = WALL;
		_table[i][1] = WALL;
		_table[i][_table_height - 4] = WALL;
		_table[i][_table_height - 3] = WALL;
		_table[i][_table_height - 2] = WALL;
		_table[i][_table_height - 1] = WALL;
	}
	_food_x = MyRandNumber(1,_table_width - 1);
	_food_y = MyRandNumber(2,_table_height - 4);
	_table[_food_x][_food_y] = FOOD;
	SetSoftkey(false, true);
	_startTime = System.currentTimeMillis();
}

static void SnakeInit()
{
	_snake = new int[_snake_max_length][2];
	int sx = 10;
	int sy = 12;
	for(int i=0; i<_snake_length; i++)
	{
		_snake[i][0] = sx;
		_snake[i][1] = sy + i;
		// _table[_snake[i][0]][_snake[i][1]] = BODY;
	}
}

static void paint_snake(Graphics g)
{
	g.setColor(255,0,0);
	g.fillRect((_snake[0][0]+1)*UNIT_WIDTH, (_snake[0][1]+1)*UNIT_WIDTH, UNIT_WIDTH, UNIT_WIDTH);
	
	g.setColor(0, 0, 250);
	for(int i=1; i<_snake_length; i++)
	{
		g.fillRect((_snake[i][0]+1)*UNIT_WIDTH, (_snake[i][1]+1)*UNIT_WIDTH, UNIT_WIDTH, UNIT_WIDTH);
	}
}
static int getSnakeState()
{
	if(_table[_snake[0][0]][_snake[0][1]] == WALL)
		return COLLIDE_WALL;
	if(_table[_snake[0][0]][_snake[0][1]] == FOOD)
		return EAT_FOOD;
	for(int i=1; i<_snake_length; i++)
	{
		if(_snake[0][0] == _snake[i][0] && _snake[0][1] == _snake[i][1])
			return COLLIDE_BODY;
	}
	return RUNNING;
}
static void SnakeMove()
{
	// _table[_snake[_snake_length-1][0]][_snake[_snake_length-1][1]] = BODY;
	for(int i=_snake_length-1; i>0; i--)
	{
		_snake[i][0] = _snake[i-1][0];
		_snake[i][1] = _snake[i-1][1];
	}
	switch(_snake_direction)
	{
		case MOVE_UP:
			_snake[0][1]--;
			break;
		case MOVE_DOWN:
			_snake[0][1]++;
			break;
		case MOVE_LEFT:
			_snake[0][0]--;
			break;
		case MOVE_RIGHT:
			_snake[0][0]++;
			break;
		default:
			break;
	}
	// _table[_snake[0][0]][_snake[0][1]] = BODY;
}
static void StateGamePlayInit()
{
	_level = 1;
	_snake_max_length = 20;
	_snake_length = 5;
	
	// _snake_state = START_LEVEL;
	_snake_state = RUNNING;
	_snake_direction = MOVE_UP;
	_table_height = 30;
	_table_width = 22;
	InitTable();
	SnakeInit();
	
	try
	{
		imgGameplayBG = Image.createImage("/bg_gameplay.png");
		// PaintModule(s_g, i,m_iImgLocationX,m_iImgLocationY);
	}
	catch(Exception ex)
	{
		System.out.println("!!!! STATE_GAMEPLAY error");
	}
	strLevel = "Level: " + _level;
	strLevel = strLevel.toUpperCase();
}

static void paint_table(Graphics g)
{
	for(int j=0; j<_table_height; j++)
	{
		for(int i=0; i<_table_width; i++)
		{
			if(_table[i][j] == WALL)
			{
				s_sprMenu.PaintModule(g, WALL_UNIT, (i+1)*UNIT_WIDTH, (j+1)*UNIT_WIDTH);
			}
			else if(_table[i][j] == FOOD)
			{
				g.setColor(255,255,0);
				g.fillRect((i+1)*UNIT_WIDTH, (j+1)*UNIT_WIDTH, UNIT_WIDTH, UNIT_WIDTH);
			}
		}
	}
	paint_level_box(g);
	
}

static void paint_level_box(Graphics g)
{
	// paint level box
	g.setColor(92, 255, 0); // light green
	g.fillRect(64, 276, 110, 28); 
	s_sprMenu.PaintModule(g, INGAME_LEVEL_BOX, 60, 274);
	int w=GetStringWidth(strLevel);
	int x = s_iWidth - w;
	DrawString(g, strLevel, x/2, 284);
}

static void update_snake()
{
	if(_snake_state == RUNNING || _snake_state == EAT_FOOD)
	{
	switch(s_iPressedKey)
	{
		case CanvasKeys.UP:
			if(_snake_direction != MOVE_DOWN)
				_snake_direction = MOVE_UP;
			break;
		case CanvasKeys.DOWN:
			if(_snake_direction != MOVE_UP)
				_snake_direction = MOVE_DOWN;
			break;
		case CanvasKeys.LEFT:
			if(_snake_direction != MOVE_RIGHT)
				_snake_direction = MOVE_LEFT;
			break;
		case CanvasKeys.RIGHT:
			if(_snake_direction != MOVE_LEFT)
				_snake_direction = MOVE_RIGHT;
			break;
		default:
			break;
	}
	if(System.currentTimeMillis() - _startTime > _snake_speed)
	{
		_startTime = System.currentTimeMillis();
		SnakeMove();
		_snake_state = getSnakeState();
		switch(_snake_state)
		{
			case EAT_FOOD:
				if(_snake_length < _snake_max_length)
				{
					_table[_food_x][_food_y] = NONE;
					_food_x = MyRandNumber(1,_table_width - 1);
					_food_y = MyRandNumber(2,_table_height - 4);
					DBG("Food XY: "+_food_x + " "+_food_y);
					_table[_food_x][_food_y] = FOOD;
					_snake[_snake_length][0] = _snake[_snake_length-1][0];
					_snake[_snake_length][1] = _snake[_snake_length-1][1];
					_snake_length++;
				}
				break;
			case COLLIDE_WALL:
				DBG("*** COLLIDE_WALL");
				break;
			case COLLIDE_BODY:
				DBG("*** COLLIDE_BODY");
				break;
			case RUNNING:
				break;
			default:
				break;
		}
		}
		else if(_snake_state == COLLIDE_BODY || _snake_state == COLLIDE_WALL)
		{
			DBG("@#$%^&^%*%$&*$&(*^%&");
		}
		/*
		switch(_table[_snake[0][0]][_snake[0][1]])
		{
			case FOOD:
				_snake_state = EAT_FOOD;
				if(_snake_length < _snake_max_length)
				{
					_table[_food_x][_food_y] = NONE;
					_food_x = MyRandNumber(1,_table_width - 1);
					_food_y = MyRandNumber(1,_table_height - 1);
					_table[_food_x][_food_y] = FOOD;
					_snake[_snake_length][0] = _snake[_snake_length-1][0];
					_snake[_snake_length][1] = _snake[_snake_length-1][1];
					_snake_length++;
				}
				break;
			case WALL:
				DBG("*** collision with wall");
				_snake_state = COLLIDE_WALL;
				break;
			case BODY:
				DBG("--- collision with Body");
				_snake_state = COLLIDE_BODY;
				break;
			default:
				_snake_state = RUNNING;
				break;
		}
		*/
	}

	
}
static void StateGamePlayUpdate()
{
	switch(s_iReleasedKey)
	{
		case CanvasKeys.SK_RIGHT:
			_menu_last_item_selected = 0;
			SwitchState(STATE_IGM);
			break;	
		case CanvasKeys.UP:
		case CanvasKeys.DOWN:
		case CanvasKeys.LEFT:
		case CanvasKeys.RIGHT:
			_snake_speed = 400;
			s_iRepeatedKey = 0;
			break;
		default:
			break;
	}
	switch(s_iRepeatedKey)
	{
		case CanvasKeys.UP:
		case CanvasKeys.DOWN:
		case CanvasKeys.LEFT:
		case CanvasKeys.RIGHT:
			_snake_speed = 200;
			break;
		default:
			break;
	}
	update_snake();
	
}

static void StateGamePlayPaint(Graphics g)
{
	g.drawImage(imgGameplayBG, 0, 0, 0);
	
	paint_snake(g);
	paint_table(g);
}

static void StateGamePlayExit()
{
	imgGameplayBG = null;
	_table = null;
}